home *** CD-ROM | disk | FTP | other *** search
- #define LIBQBUILD_CORE
- #include "../include/libqbuild.h"
-
- //
- // command line flags
- //
- int subdivide_size = 240;
-
- struct brushset *brushset;
-
- int valid;
-
- char bspfilename[NAMELEN_PATH];
- char pointfilename[NAMELEN_PATH];
- char portfilename[NAMELEN_PATH];
- char hullfilename[NAMELEN_PATH];
-
- char *argv0; // changed after fork();
-
- bool worldmodel;
-
- int hullnum;
-
- int c_activefaces, c_peakfaces;
- int c_activeleafs, c_peakleafs;
- int c_activesurfaces, c_peaksurfaces;
- int c_activeportals, c_peakportals;
-
- //===========================================================================
-
- void PrintMemory(void)
- {
- int i, j;
- int a, b;
-
- mprintf(" faces : %5i, %7i (%5i, %7i)\n", c_activefaces, j = c_activefaces * sizeof(struct visfacet),
- c_peakfaces, i = c_peakfaces * sizeof(struct visfacet));
- a = j;
- b = i;
- mprintf(" surfaces: %5i, %7i (%5i, %7i)\n", c_activesurfaces, j = c_activesurfaces * sizeof(struct surface),
- c_peaksurfaces, i = c_peaksurfaces * sizeof(struct surface));
- a += j;
- b += i;
- mprintf(" windings: %5i, %7i (%5i, %7i)\n", c_activewindings, j = c_activewindings * sizeof(struct winding),
- c_peakwindings, i = c_peakwindings * sizeof(struct winding));
- a += j;
- b += i;
- mprintf(" portals : %5i, %7i (%5i, %7i)\n", c_activeportals, j = c_activeportals * sizeof(struct portal),
- c_peakportals, i = c_peakportals * sizeof(struct portal));
- a += j;
- b += i;
- mprintf("-------------------------------------------\n");
- mprintf(" %7i ( %7i)\n\n", a, b);
- }
-
- /*
- * ===========
- * AllocLeaf
- * ===========
- */
- struct visleaf *AllocLeaf(register int prtals)
- {
- struct visleaf *l;
-
- c_activeleafs++;
- if (c_activeleafs > c_peakleafs)
- c_peakleafs = c_activeleafs;
-
- if(!(l = (struct visleaf *)tmalloc(sizeof(struct visleaf))))
- Error("AllocLeaf: failed to allocate leaf!\n");
- #ifdef DYNAMIC_EDGES
- /* at least one point available */
- if(prtals < 0)
- prtals = 0;
- if(!(l->portals = (struct visportal **)tmalloc((prtals) * sizeof(struct visportal *))))
- Error("AllocLeaf: failed to allocate portals!\n");
- #endif
- return l;
- }
-
-
- void RecalcLeaf(register struct visleaf *l) {
- #ifdef DYNAMIC_EDGES
- /* at least one point available */
- int prtals = l->numportals;
- if(prtals < 0)
- prtals = 0;
- if(!(l->portals = (struct visportal **)trealloc(l->portals , (prtals) * sizeof(struct visportal *))))
- Error("RecalcFace: failed to allocate face!\n");
- #endif
- }
-
- void FreeLeaf(register struct visleaf *l)
- {
- c_activeleafs--;
- #ifdef DYNAMIC_EDGES
- tfree(l->portals);
- #endif
- tfree(l);
- }
-
- /*
- * ===========
- * AllocFace
- * ===========
- */
- struct visfacet *AllocFace(register int points)
- {
- struct visfacet *f;
-
- c_activefaces++;
- if (c_activefaces > c_peakfaces)
- c_peakfaces = c_activefaces;
-
- if(!(f = (struct visfacet *)tmalloc(sizeof(struct visfacet))))
- Error("AllocFace: failed to allocate face!\n");
- //memset(f, 0, sizeof(struct visfacet));
- f->planenum = -1;
- #ifdef DYNAMIC_EDGES
- /* at least one point available */
- if(points < 0)
- points = 0;
- if(!(f->pts = (vec3_t *)tmalloc((points) * sizeof(vec3_t))))
- Error("AllocFace: failed to allocate points!\n");
- if(!(f->edges = (int *) tmalloc((points) * sizeof(int) )))
- Error("AllocFace: failed to allocate edges!\n");
- #endif
- return f;
- }
-
- void CopyFace(register struct visfacet *out, register struct visfacet *in) {
- #ifdef DYNAMIC_EDGES
- /* at least one point available */
- short int points = in->numpoints;
- vec3_t *pts;
- int *edges;
-
- if(points < 0)
- points = 0;
- tfree(out->pts);
- tfree(out->edges);
- if(!(pts = (vec3_t *)tmalloc((points) * sizeof(vec3_t))))
- Error("CopyFace: failed to allocate face!\n");
- if(!(edges = (int *) tmalloc((points) * sizeof(int) )))
- Error("CopyFace: failed to allocate face!\n");
- if(points) {
- memcpy(pts , in->pts , points * sizeof(vec3_t));
- memcpy(edges, in->edges, points * sizeof(int) );
- }
- #endif
- memcpy(out, in, sizeof(struct visfacet));
- #ifdef DYNAMIC_EDGES
- out->pts = pts;
- out->edges = edges;
- #endif
- }
-
- void RecalcFace(register struct visfacet *f) {
- #ifdef DYNAMIC_EDGES
- /* at least one point available */
- short int points = f->numpoints;
- if(points < 0)
- points = 0;
- if(!(f->pts = (vec3_t *)trealloc(f->pts , (points) * sizeof(vec3_t))))
- Error("RecalcFace: failed to allocate face!\n");
- if(!(f->edges = (int *) trealloc(f->edges, (points) * sizeof(int) )))
- Error("RecalcFace: failed to allocate face!\n");
- #endif
- }
-
- void FreeFace(register struct visfacet *f)
- {
- c_activefaces--;
- #ifdef DYNAMIC_EDGES
- tfree(f->pts);
- tfree(f->edges);
- #endif
- tfree(f);
- }
-
- /*
- * ===========
- * AllocSurface
- * ===========
- */
- struct surface *AllocSurface(void)
- {
- struct surface *s;
-
- if(!(s = (struct surface *)tmalloc(sizeof(struct surface))))
- Error("AllocSurface: failed to allocate surface!\n");
- //memset(s, 0, sizeof(struct surface));
-
- c_activesurfaces++;
- if (c_activesurfaces > c_peaksurfaces)
- c_peaksurfaces = c_activesurfaces;
-
- return s;
- }
-
- void FreeSurface(register struct surface *s)
- {
- c_activesurfaces--;
- tfree(s);
- }
-
- /*
- * ===========
- * AllocPortal
- * ===========
- */
- struct portal *AllocPortal(void)
- {
- struct portal *p;
-
- c_activeportals++;
- if (c_activeportals > c_peakportals)
- c_peakportals = c_activeportals;
-
- if(!(p = (struct portal *)tmalloc(sizeof(struct portal))))
- Error("AllocPortal: failed to allocate portal!\n");
- //memset(p, 0, sizeof(struct portal));
-
- return p;
- }
-
- void FreePortal(register struct portal *p)
- {
- c_activeportals--;
- tfree(p);
- }
-
- /*
- * ===========
- * AllocNode
- * ===========
- */
- struct node *AllocNode(void)
- {
- struct node *n;
-
- if(!(n = (struct node *)tmalloc(sizeof(struct node))))
- Error("AllocNode: failed to allocate node!\n");
- //memset(n, 0, sizeof(struct node));
-
- return n;
- }
-
- /*
- * ===========
- * AllocBrush
- * ===========
- */
- struct brush *AllocBrush(void)
- {
- struct brush *b;
-
- if(!(b = (struct brush *)tmalloc(sizeof(struct brush))))
- Error("AllocNode: failed to allocate node!\n");
- //memset(b, 0, sizeof(struct brush));
-
- return b;
- }
-
- //===========================================================================
-
- /*
- * ===============
- * ProcessEntity
- * ===============
- */
- void ProcessEntity(__memBase, register int entnum)
- {
- struct entity *ent;
- char mod[80];
- struct surface *surfs;
- struct node *nodes;
- struct brushset *bs;
-
- ent = &bspMem->mapentities[entnum];
- if (!ent->brushes)
- return; // non-bmodel entity
-
- if (entnum > 0) {
- worldmodel = FALSE;
- if (entnum == 1)
- mprintf("----- Internal Entities ---\n");
- sprintf(mod, "*%i", bspMem->nummodels);
-
- if (hullnum == 0)
- mprintf(" - MODEL: %s\n", mod);
- SetKeyValue(ent, "model", mod);
- }
- else
- worldmodel = TRUE;
-
- //
- // take the brush_ts and clip off all overlapping and contained faces,
- // leaving a perfect skin of the model with no hidden faces
- //
- bs = Brush_LoadEntity(bspMem, ent, hullnum);
-
- if (!bs->brushes) {
- PrintEntity(ent);
- Error("Entity with no valid brushes");
- }
-
- brushset = bs;
- surfs = CSGFaces(bspMem, bs);
-
- if (hullnum != 0) {
- nodes = SolidBSP(bspMem, surfs, TRUE);
- if (entnum == 0 && !(bspMem->bspOptions & QBSP_NOFILL)) // assume non-world bmodels are simple
- {
- PortalizeWorld(bspMem, nodes);
- if (FillOutside(bspMem, nodes, pointfilename)) {
- surfs = GatherNodeFaces(bspMem, nodes);
- nodes = SolidBSP(bspMem, surfs, FALSE); // make a really good tree
- }
- FreeAllPortals(nodes);
- }
- WriteNodePlanes(bspMem, nodes);
- WriteClipNodes(bspMem, nodes);
- BumpModel(bspMem, hullnum);
- }
- else {
- //
- // SolidBSP generates a node tree
- //
- // if not the world, make a good tree first
- // the world is just going to make a bad tree
- // because the outside filling will force a regeneration later
- nodes = SolidBSP(bspMem, surfs, entnum == 0);
-
- //
- // build all the portals in the bsp tree
- // some portals are solid polygons, and some are paths to other leafs
- //
- if (entnum == 0 && !(bspMem->bspOptions & QBSP_NOFILL)) // assume non-world bmodels are simple
- {
- PortalizeWorld(bspMem, nodes);
-
- if (FillOutside(bspMem, nodes, pointfilename)) {
- FreeAllPortals(nodes);
-
- // get the remaining faces together into surfaces again
- surfs = GatherNodeFaces(bspMem, nodes);
-
- // merge polygons
- MergeAll(bspMem, surfs);
-
- // make a really good tree
- nodes = SolidBSP(bspMem, surfs, FALSE);
-
- // make the real portals for vis tracing
- PortalizeWorld(bspMem, nodes);
-
- // save portal file for vis tracing
- WritePortalfile(bspMem, nodes, portfilename);
-
- // fix tjunctions
- if(!(bspMem->bspOptions & QBSP_NOTJUNC))
- tjunc(nodes);
- }
- FreeAllPortals(nodes);
- }
-
- WriteNodePlanes(bspMem, nodes);
- MakeFaceEdges(bspMem, nodes);
- WriteDrawNodes(bspMem, nodes);
- }
- }
-
- /*
- * =================
- * UpdateEntLump
- *
- * =================
- */
- void UpdateEntLump(__memBase)
- {
- int m, entnum;
- char mod[80];
- FILE *bspFile;
-
- m = 1;
- for (entnum = 1; entnum < bspMem->nummapentities; entnum++) {
- if (!bspMem->mapentities[entnum].brushes)
- continue;
- sprintf(mod, "*%i", m);
- SetKeyValue(&bspMem->mapentities[entnum], "model", mod);
- m++;
- }
-
- mprintf(" - updating bspMem->mapentities lump...\n");
-
- FreeClusters(bspMem, 0);
- if((bspFile = fopen(bspfilename, READWRITE_BINARY_OLD))) {
- bspMem = LoadBSP(bspFile, ALL_LUMPS);
- WriteEntitiesToString(bspMem);
- WriteBSP(bspFile, bspMem);
- FreeClusters(bspMem, 0);
- tfree(bspMem);
- fclose(bspFile);
- }
- }
-
- //===========================================================================
-
- /*
- * =================
- * WriteClipHull
- *
- * Write the clipping hull out to a text file so the parent process can get it
- * =================
- */
- void WriteClipHull(__memBase)
- {
- FILE *f;
- int i;
- struct dplane_t *p;
- struct dclipnode_t *d;
-
- hullfilename[strlen(hullfilename) - 1] = '0' + hullnum;
-
- mprintf("----- WriteClipHull -----\n");
- mprintf(" - writing %s\n", hullfilename);
-
- f = fopen(hullfilename, "w");
- if (!f)
- Error("Couldn't open %s", hullfilename);
-
- fprintf(f, "%i\n", bspMem->nummodels);
-
- for (i = 0; i < bspMem->nummodels; i++)
- fprintf(f, "%i\n", bspMem->dmodels[i].headnode[hullnum]);
-
- fprintf(f, "\n%i\n", bspMem->numclipnodes);
-
- for (i = 0; i < bspMem->numclipnodes; i++) {
- d = &bspMem->dclipnodes[i];
- p = &bspMem->dplanes[d->planenum];
- // the node number is only written out for human readability
- fprintf(f, "%5i : %g %g %g %g : %5i %5i\n", i, p->normal[0], p->normal[1], p->normal[2], p->dist, d->children[0], d->children[1]);
- }
-
- fclose(f);
- }
-
- /*
- * =================
- * ReadClipHull
- *
- * Read the files written out by the child processes
- * =================
- */
- void ReadClipHull(__memBase, register int hullnum)
- {
- FILE *f;
- int i, j, n;
- int firstclipnode;
- struct dplane_t p;
- struct dclipnode_t *d;
- int c1, c2;
- float f1, f2, f3, f4;
- int junk;
- vec3_t norm;
-
- hullfilename[strlen(hullfilename) - 1] = '0' + hullnum;
-
- f = fopen(hullfilename, "r");
- if (!f)
- Error("Couldn't open %s", hullfilename);
-
- if (fscanf(f, "%i\n", &n) != 1)
- Error("Error parsing %s", hullfilename);
-
- if (n != bspMem->nummodels)
- Error("ReadClipHull: hull had %i models, base had %i", n, bspMem->nummodels);
-
- for (i = 0; i < n; i++) {
- fscanf(f, "%i\n", &j);
- bspMem->dmodels[i].headnode[hullnum] = bspMem->numclipnodes + j;
- }
-
- fscanf(f, "\n%i\n", &n);
- firstclipnode = bspMem->numclipnodes;
-
- for (i = 0; i < n; i++) {
- if (bspMem->numclipnodes == bspMem->max_numclipnodes)
- ExpandClusters(bspMem, LUMP_CLIPNODES);
- d = &bspMem->dclipnodes[bspMem->numclipnodes];
- bspMem->numclipnodes++;
- if (fscanf(f, "%i : %g %g %g %g : %i %i\n", &junk, &f1, &f2, &f3, &f4, &c1, &c2) != 7)
- Error("Error parsing %s", hullfilename);
-
- p.normal[0] = f1;
- p.normal[1] = f2;
- p.normal[2] = f3;
- p.dist = f4;
-
- norm[0] = f1;
- norm[1] = f2;
- norm[2] = f3; // vec_t precision
-
- p.type = PlaneTypeForNormal(norm);
-
- d->children[0] = c1 >= 0 ? c1 + firstclipnode : c1;
- d->children[1] = c2 >= 0 ? c2 + firstclipnode : c2;
- d->planenum = FindFinalPlane(bspMem, &p);
- }
-
- }
-
- /*
- * =================
- * CreateSingleHull
- *
- * =================
- */
- void CreateSingleHull(__memBase)
- {
- int entnum;
-
- // for each entity in the map file that has geometry
- for (entnum = 0; entnum < bspMem->nummapentities; entnum++)
- ProcessEntity(bspMem, entnum);
-
- if (hullnum)
- WriteClipHull(bspMem);
- }
-
- /*
- * =================
- * CreateHulls
- *
- * =================
- */
- void CreateHulls(__memBase)
- {
- // commanded to create a single hull only
- if (hullnum) {
- CreateSingleHull(bspMem);
- exit(0);
- }
-
- // commanded to use the allready existing hulls 1 and 2
- if (bspMem->bspOptions & QBSP_USEHULLS) {
- CreateSingleHull(bspMem);
- return;
- }
-
- // commanded to ignore the hulls altogether
- if (bspMem->bspOptions & QBSP_NOCLIP) {
- CreateSingleHull(bspMem);
- return;
- }
-
- // create all the hulls
-
- // create the hulls sequentially
- mprintf(" - building hulls sequentially...\n");
-
- hullnum = 1;
- CreateSingleHull(bspMem);
-
- bspMem->nummodels = 0;
- bspMem->numplanes = 0;
- bspMem->numclipnodes = 0;
- hullnum = 2;
- CreateSingleHull(bspMem);
-
- bspMem->nummodels = 0;
- bspMem->numplanes = 0;
- bspMem->numclipnodes = 0;
- hullnum = 0;
- CreateSingleHull(bspMem);
- }
-
- /*
- * =================
- * ProcessMem
- * =================
- */
- void ProcessMem(__memBase, register char *filebase)
- {
- // create filenames
- strcpy(bspfilename, filebase);
- ReplaceExt(bspfilename, "bsp");
- strcpy(hullfilename, filebase);
- ReplaceExt(hullfilename, "h0");
- strcpy(portfilename, filebase);
- ReplaceExt(portfilename, "prt");
- strcpy(pointfilename, filebase);
- ReplaceExt(pointfilename, "pts");
-
- if (bspMem->bspOptions & QBSP_ONLYENTS)
- UpdateEntLump(bspMem);
- else {
- if (!(bspMem->bspOptions & QBSP_USEHULLS)) {
- hullfilename[strlen(hullfilename) - 1] = '1';
- remove(hullfilename);
- hullfilename[strlen(hullfilename) - 1] = '2';
- remove(hullfilename);
- }
- remove(portfilename);
- remove(pointfilename);
-
- // the clipping hulls will be written out to text files by forked processes
- CreateHulls(bspMem);
-
- ReadClipHull(bspMem, 1);
- ReadClipHull(bspMem, 2);
-
- WriteEntitiesToString(bspMem);
- }
- }
-
- bool qbsp(__memBase, int hullNum, int subDivide, char *filebase)
- {
- if(hullNum) {
- hullnum = hullNum;
- mprintf("use hull %d\n", hullNum);
- }
- if(subDivide) {
- subdivide_size = subDivide;
- mprintf("subdivide %d\n", subDivide);
- }
-
- ProcessMem(bspMem, filebase);
- PrintMemory();
-
- return TRUE;
- }
-
-